package com.ubird.tetris.block;

import java.awt.Graphics;
import java.util.Arrays;
import java.util.Random;

public class TetrisBlock {
    public final static TetrisBlock POINT = new TetrisBlock(
            new int[][][] { { { 0, 0, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } });
    public final static TetrisBlock SQUARE = new TetrisBlock(
            new int[][][] { { { 0, 1, 1, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } });
    public final static TetrisBlock LINE = new TetrisBlock(
            new int[][][] { { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 } } });
    public final static TetrisBlock Z = new TetrisBlock(
            new int[][][] { { { 0, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 0, 0 }, { 1, 1, 0, 0 }, { 1, 0, 0, 0 }, { 0, 0, 0, 0 } } });
    public final static TetrisBlock VZ = new TetrisBlock(
            new int[][][] { { { 0, 0, 0, 0 }, { 0, 1, 1, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 1, 0, 0, 0 }, { 1, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } } });
    public final static TetrisBlock T = new TetrisBlock(
            new int[][][] { { { 0, 0, 0, 0 }, { 1, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 0, 0 }, { 1, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } } });
    public final static TetrisBlock VL = new TetrisBlock(
            new int[][][] { { { 1, 0, 0, 0 }, { 1, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 1, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 0, 0, 0 }, { 1, 1, 1, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 1, 1, 0, 0 }, { 0, 0, 0, 0 } } });
    public final static TetrisBlock L = new TetrisBlock(
            new int[][][] { { { 0, 0, 1, 0 }, { 1, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 } },
                    { { 0, 0, 0, 0 }, { 1, 1, 1, 0 }, { 1, 0, 0, 0 }, { 0, 0, 0, 0 } },
                    { { 1, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 0, 0 } } });

    static TetrisBlock[] ALL_BLOCKS = { POINT, SQUARE, LINE, Z, VZ, T, L, VL };

    // public final static TetrisBlock SUPER_LINE = new TetrisBlock(new
    // int[][][]{{{0,0,0,0},{1,1,1,1,1,1},{1,1,1,1,1,1},{0,0,0,0}},
    // {{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0}}});
    // static TetrisBlock[] ALL_BLOCKS = {SUPER_LINE};

    private final int[][][] dirShapes;
    private int dir;
    private int x;
    private int y;

    private final static Random rand = new Random();

    TetrisBlock(TetrisBlock block) {
        this.dir = block.dir;
        this.x = block.x;
        this.y = block.y;
        this.dirShapes = block.dirShapes;
    }

    TetrisBlock(int[][][] dirShapes) {
        this.dirShapes = dirShapes;
    }

    public void init(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public synchronized void down() {
        y++;
    }

    public int[][] getShap() {
        return dirShapes[dir];
    }

    public int getXInWorld() {
        return x;
    }

    public int getYInWorld() {
        return y;
    }

    public int[][] rotate() {
        dir = (dir + 1) % dirShapes.length;
        return dirShapes[dir];
    }

    public void draw(Graphics g, int gridSize) {
        int[][] shap = getShap();
        for (int i = 0; i < shap.length; i++) {
            for (int j = 0; j < shap[i].length; j++) {
                if (shap[i][j] == 1) {
                    g.fill3DRect((j + x) * gridSize, (i + y) * gridSize, gridSize, gridSize, false);
                }
            }
        }
    }

    public static TetrisBlock random() {
        return ALL_BLOCKS[rand.nextInt(ALL_BLOCKS.length)];
    }

    public void left() {
        x--;
    }

    public void right() {
        x++;
    }

    public TetrisBlock copyDown() {
        TetrisBlock tetrisBlock = new TetrisBlock(this);
        tetrisBlock.down();
        return tetrisBlock;
    }

    public TetrisBlock copyLeft() {
        TetrisBlock tetrisBlock = new TetrisBlock(this);
        tetrisBlock.left();
        return tetrisBlock;
    }

    public TetrisBlock copyRight() {
        TetrisBlock tetrisBlock = new TetrisBlock(this);
        tetrisBlock.right();
        return tetrisBlock;
    }

    public TetrisBlock copyRotate() {
        TetrisBlock tetrisBlock = new TetrisBlock(this);
        tetrisBlock.rotate();
        return tetrisBlock;
    }

    public TetrisBlock copy() {
        TetrisBlock tetrisBlock = new TetrisBlock(this);
        return tetrisBlock;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < dirShapes.length; i++) {
            sb.append(i).append(":[");
            for (int j = 0; j < dirShapes[i].length; j++) {
                sb.append(Arrays.toString(dirShapes[i][j])).append('\n');
            }
            sb.append("]\n");
        }
        return "TetrisBlock[\n" + "   x: " + x + "\n" + "   y: " + y + "\n" + "   dir: " + dir + "\n" + "   shape: "
                + sb.toString() + "\n" + "]";
    }
}
